package psi.services;

import java.util.ArrayList;
import java.util.List;

import com.jfinal.aop.Before;
import com.jfinal.kit.HashKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.tx.Tx;

import psi.common.FIdConst;
import psi.common.PSIConst;
import psi.common.PSISessionKit;
import psi.common.Result;

/**
 * 用户 Service
 * 
 * @author 李静波
 *
 */
public class UserService extends PSIBaseService {

	private static final String LOG_CATEGORY_NAME = "用户管理";

	/**
	 * 执行登录操作
	 * 
	 * @param loginName
	 *            用户登录名
	 * @param password
	 *            登录密码
	 * @return Result
	 */
	public Result doLogin(String loginName, String password) {
		Result result = new Result();

		String sql = "";
		sql += " select id from t_user ";
		sql += " where login_name = ? and password = ? and enabled = 1 ";

		String userId = Db.queryStr(sql, loginName, HashKit.md5(password));

		if (userId != null) {
			PSISessionKit.get().setAttribute("loginUserId", userId);
			result.setSuccess(true);
			result.setId(userId);

			new BizlogService().insertBizlog("登录系统", "系统");
		} else {
			PSISessionKit.get().setAttribute("loginUserId", null);
			result.setMsg("用户名或者密码错误");
		}

		return result;
	}

	/**
	 * 当前登录用户的Id
	 * 
	 * @return
	 */
	public String getLoginUserId() {
		return (String) PSISessionKit.get().getAttribute("loginUserId");
	}

	/**
	 * 当前登录用户的登录名
	 * 
	 * @return
	 */
	public String getLoingName() {
		String sql = "select login_name from t_user where id = ?";
		return Db.queryStr(sql, getLoginUserId());
	}

	/**
	 * 判断当前用户是否具有fid的权限
	 * 
	 * @param fid
	 *            功能id
	 * @return true: 有权限
	 */
	public boolean hasPermission(String fid) {
		String userId = getLoginUserId();
		if (userId == null) {
			return false;
		}

		// 修改我的密码，重新登录，首页，使用帮助，关于，购买商业服务，这六个功能对所有的在线用户均不需要特别的权限
		List<String> idList = new ArrayList<String>();
		idList.add(FIdConst.CHANGE_MY_PASSWORD);
		idList.add(FIdConst.RELOGIN);
		idList.add(FIdConst.HOME);
		idList.add(FIdConst.HELP);
		idList.add(FIdConst.ABOUT);
		idList.add(FIdConst.PSI_SERVICE);

		if (fid == null || idList.contains(fid)) {
			return true;
		}

		String sql = "";
		sql += " select count(*) as cnt ";
		sql += " from  t_role_user ru, t_role_permission rp, t_permission p ";
		sql += " where ru.user_id = ? and ru.role_id = rp.role_id ";
		sql += "      and rp.permission_id = p.id and p.fid = ? ";

		return Db.queryLong(sql, userId, fid) > 0;
	}

	public String getDemoInfo() {
		if (isDemo()) {
			return "您当前处于演示环境，默认的登录名和密码均为 admin <br/>更多帮助请点击 [帮助] 按钮来查看 <br /><div style='color:red'>请勿在演示环境中保存正式数据，演示数据库通常每天在21:00后会清空一次</div>";
		} else {
			return "";
		}
	}

	public String getLoignUserNameWithOrgFullName() {
		String userId = getLoginUserId();
		if (userId == null) {
			return null;
		}

		String sql = "";
		sql += " select o.full_name ";
		sql += " from t_org o, t_user u ";
		sql += " where o.id = u.org_id and u.id = ? ";
		String orgFullName = Db.queryStr(sql, userId);
		if (orgFullName == null) {
			return null;
		}

		sql = "select login_name from t_user where id = ?";
		String userName = Db.queryStr(sql, userId);
		if (userName == null) {
			return null;
		}

		return (orgFullName + "\\" + userName).replace("\\", "\\\\");
	}

	private List<Record> allOrgsInternal(String parentId) {
		List<Record> result = new ArrayList<Record>();
		String sql = "";
		sql += "select id, name, org_code, full_name, data_org ";
		sql += " from t_org ";
		sql += " where parent_id = ? ";
		sql += " order by org_code";
		List<Record> orgs = Db.find(sql, parentId);

		for (Record org : orgs) {
			Record item = new Record();
			item.set("id", org.getStr("id"));
			item.set("text", org.getStr("name"));
			item.set("orgCode", org.getStr("org_code"));
			item.set("fullName", org.getStr("full_name"));
			item.set("dataOrg", org.getStr("data_org"));

			String id = org.getStr("id");
			List<Record> children = allOrgsInternal(id); // 自身递归调用

			item.set("children", children);
			item.set("leaf", children.isEmpty());
			item.set("expanded", true);

			result.add(item);
		}

		return result;
	}

	public List<Record> allOrgs() {
		String sql = "";
		sql += "select id, name, org_code, full_name, data_org ";
		sql += " from t_org ";
		sql += " where parent_id is null ";
		sql += " order by org_code";

		List<Record> orgs = Db.find(sql);

		List<Record> result = new ArrayList<Record>();
		for (Record org : orgs) {
			Record item = new Record();
			item.set("id", org.getStr("id"));
			item.set("text", org.getStr("name"));
			item.set("orgCode", org.getStr("org_code"));
			item.set("fullName", org.getStr("full_name"));
			item.set("dataOrg", org.getStr("data_org"));

			String parentId = org.getStr("id");
			List<Record> children = allOrgsInternal(parentId);

			item.set("children", children);
			item.set("leaf", children.isEmpty());
			item.set("expanded", true);

			result.add(item);
		}

		return result;
	}

	public Record users(Record params) {
		int start = Integer.parseInt(params.getStr("start"));
		int limit = Integer.parseInt(params.getStr("limit"));
		String orgId = params.getStr("orgId");

		List<Record> result = new ArrayList<Record>();

		String sql = "";
		sql += " select id, login_name,  name, enabled, org_code, gender, birthday, id_card_number, tel, ";
		sql += "   tel02, address, data_org ";
		sql += "   from t_user ";
		sql += " where org_id = ? order by org_code limit ? , ?";

		List<Record> data = Db.find(sql, orgId, start, limit);

		for (Record item : data) {
			Record user = new Record();

			user.set("id", item.getStr("id"));
			user.set("loginName", item.getStr("login_name"));
			user.set("name", item.getStr("name"));
			user.set("enabled", item.getInt("enabled"));
			user.set("orgCode", item.getStr("org_code"));
			user.set("gender", item.getStr("gender"));
			user.set("birthday", item.getStr("birthday"));
			user.set("idCardNumber", item.getStr("id_card_number"));
			user.set("tel", item.getStr("tel"));
			user.set("tel02", item.getStr("tel02"));
			user.set("address", item.getStr("address"));
			user.set("dataOrg", item.getStr("data_org"));

			result.add(user);
		}

		sql = "select count(*) from t_user where org_id = ?";
		Long count = Db.queryLong(sql, orgId);

		return new Record().set("dataList", result).set("totalCount", count);
	}

	@Before(Tx.class)
	public Result editOrg(Record params) {
		String id = params.getStr("id");
		String name = params.getStr("name");
		String orgCode = params.getStr("orgCode");
		String parentId = params.getStr("parentId");

		if (id == null || id.isEmpty()) {
			// 新建组织机构
			String sql = "select count(*) from t_org where org_code = ?";
			Long count = Db.queryLong(sql, orgCode);
			if (count > 0) {
				bad("编码[" + orgCode + "]已经存在");
			}

			id = IdGenService.newId();

			sql = "select full_name from t_org where id = ?";
			String fullName = Db.queryStr(sql, parentId);
			if (fullName == null) {
				fullName = name;
				parentId = null;
			} else {
				fullName = fullName + "\\" + name;
			}

			String dataOrg = "";

			if (parentId == null) {
				sql = "";
				sql += " select data_org from t_org where parent_id is null ";
				sql += "   order by data_org desc limit 1";
				dataOrg = Db.queryStr(sql);
				if (dataOrg == null) {
					dataOrg = "01";
				} else {
					dataOrg = String.format("%1$02d", Integer.parseInt(dataOrg) + 1);
				}
			} else {
				sql = "";
				sql += " select data_org from t_org where parent_id = ? ";
				sql += "   order by data_org desc limit 1";
				dataOrg = Db.queryStr(sql, parentId);
				if (dataOrg == null) {
					sql = " select data_org from t_org where id = ?";
					dataOrg = Db.queryStr(sql, parentId);
					dataOrg += "01";
				} else {
					dataOrg = String.format("%1$0" + dataOrg.length() + "d", Integer.parseInt(dataOrg) + 1);
				}
			}

			if (parentId == null) {
				sql = "";
				sql += " insert into t_org (id, name, full_name, org_code, data_org, parent_id) ";
				sql += " values (?, ?, ?, ?, ?, null) ";
				Db.update(sql, id, name, fullName, orgCode, dataOrg);
			} else {
				sql = "";
				sql += " insert into t_org (id, name, full_name, org_code, data_org, parent_id) ";
				sql += " values (?, ?, ?, ?, ?, ?) ";
				Db.update(sql, id, name, fullName, orgCode, dataOrg, parentId);
			}

			String log = "新增组织机构：名称 = " + name + " 编码 = " + orgCode;
			new BizlogService().insertBizlog(log, LOG_CATEGORY_NAME);
		} else {
			// 编辑组织机构

			String sql = "select count(*) from t_org where org_code = ? and id <> ?";
			Long count = Db.queryLong(sql, orgCode, id);
			if (count > 0) {
				bad("编码[" + orgCode + "]已经存在");
			}

			if (id.equals(parentId)) {
				bad("上级组织机构不能是自身");
			}

			if ("".equals(parentId)) {
				parentId = null;
			}

			if (parentId != null) {
				sql = "select count(*) from t_org where id = ?";
				count = Db.queryLong(sql, parentId);
				if (count != 1) {
					bad("选择的上级组织不存在");
				}
			}

			sql = "select parent_id from t_org where id = ?";
			String oldParentId = Db.queryStr(sql, id);
			boolean changedParentId = false;
			if (oldParentId == null) {
				if (parentId != null) {
					changedParentId = true;
				}
			} else if (!oldParentId.equals(parentId)) {
				changedParentId = true;
			}

			if (changedParentId) {
				// 修改了上级组织机构，这个时候需要调整组织机构和用户的数据域
				modifyDataOrg(parentId, id);
			}

			if (parentId == null) {
				sql = "";
				sql += " update t_org ";
				sql += " set name = ? , full_name = ?, org_code = ?, parent_id = null ";
				sql += " where id = ? ";
				Db.update(sql, name, name, orgCode, id);
			} else {
				// 检查parentId是否是下级组织
				String tempParentId = parentId;
				while (tempParentId != null) {
					sql = "select parent_id from t_org where id = ?";
					tempParentId = Db.queryStr(sql, tempParentId);
					if (id.equals(tempParentId)) {
						bad("不能选择下级组织作为上级组织");
					}
				}

				sql = "select full_name from t_org where id = ?";
				String fullName = Db.queryStr(sql, parentId);
				if (fullName == null) {
					bad("上级组织机构不存在");
				}

				fullName = fullName + "\\" + name;

				sql = "";
				sql += " update t_org ";
				sql += " set name = ?, full_name = ?, org_code = ?, parent_id = ? ";
				sql += " where id = ? ";
				Db.update(sql, name, fullName, orgCode, parentId, id);
			}

			modifyFullName(id);

			String log = "编辑组织机构：名称 = " + name + " 编码 = " + orgCode;
			new BizlogService().insertBizlog(log, LOG_CATEGORY_NAME);
		}

		return ok();
	}

	/**
	 * 修改数据域
	 * 
	 * @param parentId
	 *            上级组织机构id
	 * @param id
	 *            组织机构id
	 */
	private void modifyDataOrg(String parentId, String id) {
		String sql = "";
		String dataOrg = "";
		if (parentId == null) {
			sql = "";
			sql += " select data_org from t_org ";
			sql += " where parent_id is null ";
			sql += " order by data_org desc limit 1";
			dataOrg = Db.queryStr(sql);
			if (dataOrg == null) {
				dataOrg = "00";
			}
		} else {
			sql = "select data_org from t_org where id = ?";
			String parentDataOrg = Db.queryStr(sql, parentId);
			if (parentDataOrg == null) {
				bad("数据异常[parentDataOrg == null]，请联系系统管理员");
			}

			sql = "";
			sql += " select data_org from t_org ";
			sql += " where parent_id = ? and left(data_org, " + parentDataOrg.length() + ") = ?";
			sql += " order by data_org desc limit 1";
			dataOrg = Db.queryStr(sql, parentId, parentDataOrg);
			if (dataOrg == null) {
				dataOrg = parentDataOrg + "00";
			}
		}

		dataOrg = String.format("%1$0" + dataOrg.length() + "d", Integer.parseInt(dataOrg) + 1);

		sql = "update t_org set data_org = ? where id = ?";
		Db.update(sql, dataOrg, id);

		// 调整该组织机构的员工的数据域
		sql = "select id from t_user where org_id = ? order by org_code";
		List<Record> users = Db.find(sql, id);
		for (int i = 0; i < users.size(); i++) {
			String userDataOrg = dataOrg + "0000";
			int index = Integer.parseInt(userDataOrg) + i + 1;
			userDataOrg = String.format("%1$0" + userDataOrg.length() + "d", index);

			sql = "update t_user set data_org = ? where id = ?";
			Db.update(sql, userDataOrg, users.get(i).getStr("id"));
		}

		// 处理下级组织机构
		sql = "select id from t_org where parent_id = ? order by org_code";
		List<Record> orgs = Db.find(sql, id);
		for (Record org : orgs) {
			modifyDataOrg(id, org.getStr("id")); // 递归调用自己
		}
	}

	private void modifyFullName(String parentId) {
		if (parentId == null) {
			bad("参数parentId不能为null，请联系系统管理员");
		}

		String sql = "select full_name from t_org where id = ?";
		String fullName = Db.queryStr(sql, parentId);
		if (fullName == null) {
			bad("id = " + parentId + ", 在表t_org中不存在, 请联系系统管理员");
		}

		sql = "select id, name from t_org where parent_id = ?";
		List<Record> orgs = Db.find(sql, parentId);
		for (Record org : orgs) {
			sql = "update t_org set full_name = ? where id = ?";
			Db.update(sql, fullName + "\\" + org.getStr("name"), org.getStr("id"));

			// 递归调用，处理下级组织机构
			modifyFullName(org.getStr("id"));
		}
	}

	public Record orgParentName(String id) {
		Record result = new Record();

		String sql = "select parent_id, name, org_code from t_org where id = ?";

		Record data = Db.findFirst(sql, id);
		if (data != null) {
			result.set("name", data.getStr("name"));
			result.set("orgCode", data.getStr("org_code"));
			String parentId = data.getStr("parent_id");

			sql = "select full_name from t_org where id = ?";
			String fullName = Db.queryStr(sql, parentId);
			result.set("parentOrgId", parentId);
			result.set("parentOrgName", fullName);
		}

		return result;
	}

	@Before(Tx.class)
	public Result deleteOrg(String id) {
		String sql = "select name, org_code from t_org where id = ? ";
		Record data = Db.findFirst(sql, id);

		if (data == null) {
			bad("要删除的组织机构不存在");
		}
		String orgName = data.getStr("name");
		String orgCode = data.getStr("org_code");

		sql = "select count(*) as cnt from t_org where parent_id = ? ";
		Long count = Db.queryLong(sql, id);
		if (count > 0) {
			bad("当前组织机构还有下级组织，不能删除");
		}

		sql = "select count(*) as cnt from t_user where org_id = ?";
		count = Db.queryLong(sql, id);
		if (count > 0) {
			bad("当前组织机构还有用户，不能删除");
		}

		// TODO 检查在业务中是否使用了该组织机构

		sql = " delete from t_org where id = ? ";
		Db.update(sql, id);

		String log = "删除组织机构： 名称 = " + orgName + " 编码  = " + orgCode;
		new BizlogService().insertBizlog(log, LOG_CATEGORY_NAME);

		return ok();
	}

	@Before(Tx.class)
	public Result editUser(Record params) {
		String id = params.getStr("id");
		String loginName = params.getStr("loginName");
		String name = params.getStr("name");
		String orgCode = params.getStr("orgCode");
		String orgId = params.getStr("orgId");
		String birthday = params.getStr("birthday");
		String idCardNumber = params.getStr("idCardNumber");
		String tel = params.getStr("tel");
		String tel02 = params.getStr("tel02");
		String address = params.getStr("address");
		String gender = params.getStr("gender");
		boolean enabled = Boolean.parseBoolean(params.getStr("enabled"));

		String py = new PinyinService().toYP(name);
		String sql = "";
		if (id == null || "".equals(id)) {
			// 新建用户

			// 检查登录名是否被使用
			sql = "select count(*) from t_user where login_name = ?";
			Long cnt = Db.queryLong(sql, loginName);
			if (cnt > 0) {
				bad("登录名[" + loginName + "]已经存在");
			}

			// 检查编码是否重复
			sql = "select count(*) from t_user where org_code = ?";
			cnt = Db.queryLong(sql, orgCode);
			if (cnt > 0) {
				bad("编码[" + orgCode + "]已经被使用");
			}

			// 检查组织机构是否存在
			sql = "select data_org from t_org where id = ?";
			String dataOrg = Db.queryStr(sql, orgId);
			if (dataOrg == null) {
				bad("组织机构不存在");
			}

			// 生成数据域
			sql = "";
			sql += " select data_org from t_user where org_id = ? ";
			sql += "  and left(data_org, " + dataOrg.length() + ") = ? ";
			sql += " order by data_org desc limit 1";
			String userDataOrg = Db.queryStr(sql, orgId, dataOrg);
			if (userDataOrg == null) {
				userDataOrg = dataOrg + "0000";
			}
			userDataOrg = String.format("%1$0" + userDataOrg.length() + "d", Integer.parseInt(userDataOrg) + 1);

			id = IdGenService.newId();

			// 新用户的默认密码：123456
			String password = HashKit.md5("123456");

			sql = "";
			sql += " insert into t_user (id, login_name, name, org_code, org_id, enabled, password, py, ";
			sql += "  gender, birthday, id_card_number, tel, tel02, address, data_org) ";
			sql += " values (?, ?, ?, ?, ?, ?, ?, ?, ";
			sql += "  ?, ?, ?, ?, ?, ?, ?)";
			Db.update(sql, id, loginName, name, orgCode, orgId, enabled ? 1 : 0, password, py, gender, birthday,
					idCardNumber, tel, tel02, address, userDataOrg);

			String log = "新建用户： 登录名 = " + loginName + " 姓名 = " + name + " 编码 = " + orgCode;
			new BizlogService().insertBizlog(log, LOG_CATEGORY_NAME);
		} else {
			// 编辑用户

			if (id.equals(PSIConst.ADMIN_USER_ID)) {
				if (!"admin".equals(loginName)) {
					loginName = "admin";
				}
			}

			// 检查登录名是否被使用
			sql = "select count(*) from t_user where login_name = ? and id <> ?";
			Long cnt = Db.queryLong(sql, loginName, id);
			if (cnt > 0) {
				bad("登录名[" + loginName + "]已经存在");
			}

			// 检查编码是否重复
			sql = "select count(*) from t_user where org_code = ? and id <> ?";
			cnt = Db.queryLong(sql, orgCode, id);
			if (cnt > 0) {
				bad("编码[" + orgCode + "]已经被使用");
			}

			// 检查组织机构是否存在
			sql = "select data_org from t_org where id = ?";
			String dataOrg = Db.queryStr(sql, orgId);
			if (dataOrg == null) {
				bad("组织机构不存在");
			}

			sql = "select org_id, data_org from t_user where id = ?";
			Record r = Db.findFirst(sql, id);
			String oldOrgId = r.getStr("org_id");
			String userDataOrg = r.getStr("data_org");
			if (!oldOrgId.equals(orgId)) {
				// 更改了用户的组织机构，需要调整其数据域
				sql = "";
				sql += " select data_org from t_user where org_id = ? ";
				sql += "  and left(data_org, " + dataOrg.length() + ") = ? ";
				sql += " order by data_org desc limit 1";
				userDataOrg = Db.queryStr(sql, orgId, dataOrg);
				if (userDataOrg == null) {
					userDataOrg = dataOrg + "0000";
				}
				userDataOrg = String.format("%1$0" + userDataOrg.length() + "d", Integer.parseInt(userDataOrg) + 1);
			}

			sql = "";
			sql += " update t_user ";
			sql += " set login_name = ?, name = ?, org_code = ?, ";
			sql += " 	org_id = ?, enabled = ?, py = ?, ";
			sql += " 	gender = ?, birthday = ?, id_card_number = ?, ";
			sql += " 	tel = ?, tel02 = ?, address = ?, data_org = ? ";
			sql += " where id = ? ";
			Db.update(sql, loginName, name, orgCode, orgId, enabled ? 1 : 0, py, gender, birthday, idCardNumber, tel,
					tel02, address, userDataOrg, id);

			String log = "编辑用户： 登录名 = " + loginName + " 姓名 = " + name + " 编码 = " + orgCode;
			new BizlogService().insertBizlog(log, LOG_CATEGORY_NAME);
		}

		return ok(id);
	}

	@Before(Tx.class)
	public Result deleteUser(String id) {
		if (PSIConst.ADMIN_USER_ID.equals(id)) {
			bad("不能删除admin用户");
		}

		String sql = "select name from t_user where id = ?";

		String name = Db.queryStr(sql, id);
		if (name == null) {
			bad("要删除的用户不存在");
		}

		// TODO 判断在业务单据中是否使用了该用户

		sql = "delete from t_user where id = ?";
		Db.update(sql, id);

		String log = "删除用户[" + name + "]";
		new BizlogService().insertBizlog(log, LOG_CATEGORY_NAME);

		return ok();
	}

	@Before(Tx.class)
	public Result changePassword(String id, String password) {
		if (password == null || password.length() < 5) {
			bad("密码长度不能小于5位");
		}

		String sql = "select login_name, name from t_user where id = ?";
		Record r = Db.findFirst(sql, id);
		if (r == null) {
			bad("选择的用户不存在");
		}
		String loginName = r.getStr("login_name");
		String name = r.getStr("name");

		sql = "update t_user set password = ? where id = ?";
		Db.update(sql, HashKit.md5(password), id);

		String log = "修改用户[登录名 =" + loginName + " 姓名 = " + name + "]的密码";
		new BizlogService().insertBizlog(log, LOG_CATEGORY_NAME);

		return ok();
	}

	@Before(Tx.class)
	public Result changeMyPassword(String userId, String oldPassword, String newPassword) {
		if (userId == null || !userId.equals(getLoginUserId())) {
			bad("服务器环境发生变化，请重新登录后再操作");
		}

		// 检查旧密码是否正确
		String sql = "select login_name, name from t_user where id = ?";
		Record r = Db.findFirst(sql, userId);
		if (r == null) {
			bad("服务器环境发生变化，请重新登录后再操作");
		}
		String loginName = r.getStr("login_name");
		String name = r.getStr("name");

		sql = "select count(*) as cnt from t_user where id = ? and password = ? ";
		Long cnt = Db.queryLong(sql, userId, HashKit.md5(oldPassword));
		if (cnt != 1) {
			bad("旧密码不正确");
		}

		if (newPassword == null || newPassword.length() < 5) {
			bad("密码长度不能小于5位");
		}

		sql = "update t_user set password = ? where id = ?";
		Db.update(sql, HashKit.md5(newPassword), userId);

		String log = "用户[登录名 =" + loginName + " 姓名 = " + name + "]修改了自己的登录密码";
		new BizlogService().insertBizlog(log, LOG_CATEGORY_NAME);

		return ok();
	}
	
	public String getLoginUserDataOrg() {
		String sql = "select data_org from t_user where id = ?";

		return Db.queryStr(sql, getLoginUserId());
	}
	
	/**
	 * 当前登录用户是否是admin
	 * @return true：是
	 */
	public boolean isAdmin() {
		return PSIConst.ADMIN_USER_ID.equals(getLoginUserId());
	}
}